package com.generic.mixed.type.demo3;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;

public class ProxyClass implements InvocationHandler {

	// 被代理对象的Map，这些对象通过对象内的方法名与之绑定
	private Map<String, Object> delegatesByMethod = new HashMap<String, Object>();

	public ProxyClass(TwoTuple<Object, Class<?>>... pairs) {
		for (TwoTuple<Object, Class<?>> pair : pairs) {
			for (Method m : pair.secord.getMethods()) {
				// 这里会有一定的局限性，也就是当不同的被代理对象
				// 有相同的方法时，只能调用第一个拥有该方法的被代理对象
				if (!delegatesByMethod.containsKey(m.getName()))
					delegatesByMethod.put(m.getName(), pair.first);
			}
		}
	}

	@Override
	public Object invoke(Object arg0, Method method, Object[] arg2)
			throws Throwable {
		// 通过方法名确定需要调用的被代理对象
		return method.invoke(delegatesByMethod.get(method.getName()), arg2);
	}

	public static Object newInstance(TwoTuple<Object, Class<?>>... pairs) {
		Class<?>[] interfaces = new Class<?>[pairs.length];
		for (int i = 0; i < pairs.length; i++) {
			interfaces[i] = pairs[i].secord;
		}
		ClassLoader cl = pairs[0].first.getClass().getClassLoader();
		return Proxy.newProxyInstance(cl, interfaces, new ProxyClass(pairs));
	}

}
